﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using Microsoft.Research.Kinect.Nui;
using System.Windows.Media.Media3D;
using System.Data;
using System.Linq;
using System.Speech.Recognition;

using System.ComponentModel;
using Nui.Vision;


namespace TARADesktopDoctor
{
    public partial class AssessmentROM
    {
        tara_wcf.ItaraServiceClient svc = new tara_wcf.ItaraServiceClient();

        #region offical kinect sdk variables
        Runtime nui;
        int totalFrames = 0;
        int lastFrames = 0;
        DateTime lastTime = DateTime.MaxValue;

        // We want to control how depth data gets converted into false-color data
        // for more intuitive visualization, so we keep 32-bit color frame buffer versions of
        // these, to be updated whenever we receive and process a 16-bit frame.
        const int RED_IDX = 2;
        const int GREEN_IDX = 1;
        const int BLUE_IDX = 0;
        byte[] depthFrame32 = new byte[320 * 240 * 4];


        Dictionary<JointID, Brush> jointColors = new Dictionary<JointID, Brush>() { 
            {JointID.HipCenter, new SolidColorBrush(Color.FromRgb(169, 176, 155))},
            {JointID.Spine, new SolidColorBrush(Color.FromRgb(169, 176, 155))},
            {JointID.ShoulderCenter, new SolidColorBrush(Color.FromRgb(168, 230, 29))},
            {JointID.Head, new SolidColorBrush(Color.FromRgb(200, 0,   0))},
            {JointID.ShoulderLeft, new SolidColorBrush(Color.FromRgb(79,  84,  33))},
            {JointID.ElbowLeft, new SolidColorBrush(Color.FromRgb(84,  33,  42))},
            {JointID.WristLeft, new SolidColorBrush(Color.FromRgb(255, 126, 0))},
            {JointID.HandLeft, new SolidColorBrush(Color.FromRgb(215,  86, 0))},
            {JointID.ShoulderRight, new SolidColorBrush(Color.FromRgb(33,  79,  84))},
            {JointID.ElbowRight, new SolidColorBrush(Color.FromRgb(33,  33,  84))},
            {JointID.WristRight, new SolidColorBrush(Color.FromRgb(77,  109, 243))},
            {JointID.HandRight, new SolidColorBrush(Color.FromRgb(37,   69, 243))},
            {JointID.HipLeft, new SolidColorBrush(Color.FromRgb(77,  109, 243))},
            {JointID.KneeLeft, new SolidColorBrush(Color.FromRgb(69,  33,  84))},
            {JointID.AnkleLeft, new SolidColorBrush(Color.FromRgb(229, 170, 122))},
            {JointID.FootLeft, new SolidColorBrush(Color.FromRgb(255, 126, 0))},
            {JointID.HipRight, new SolidColorBrush(Color.FromRgb(181, 165, 213))},
            {JointID.KneeRight, new SolidColorBrush(Color.FromRgb(71, 222,  76))},
            {JointID.AnkleRight, new SolidColorBrush(Color.FromRgb(245, 228, 156))},
            {JointID.FootRight, new SolidColorBrush(Color.FromRgb(77,  109, 243))}
        };
        #endregion

        #region variables for ROM
        //double maxJoint1 = 0;
        double maxJoint2 = 0;
        double maxJoint3 = 0;
        double maxJoint4 = 0;
        double maxJoint5 = 0;
        //double maxJoint6 = 0;
        //double maxJoint7 = 0;
        double maxJoint8 = 0;
        double maxJoint9 = 0;
        double maxJoint10 = 0;
        double maxJoint11 = 0;
        double maxJoint12 = 0;
        //double maxJoint13 = 0;
        //double maxJoint14 = 0;
        //double minJoint1 = 0;
        double maxJoint14 = 0;
        double maxJoint15 = 0;
        double maxJoint16 = 0;
        double maxJoint17 = 0;
        //double maxJoint18 = 0;
        double maxJoint19 = 0;
        //double maxJoint20 = 0;
        double maxJoint21 = 0;

        double minJoint2 = 0;
        double minJoint3 = 0;
        double minJoint4 = 0;
        double minJoint5 = 0;
        //double minJoint6 = 0;
        //double minJoint7 = 0;
        double minJoint8 = 0;
        double minJoint9 = 0;
        double minJoint10 = 0;
        double minJoint11 = 0;
        double minJoint12 = 0;
        //double minJoint13 = 0;
        //double minJoint14 = 0;
        double minJoint14 = 0;
        double minJoint15 = 0;
        double minJoint16 = 0;
        double minJoint17 = 0;
        //double minJoint18 = 0;
        double minJoint19 = 0;
        //double minJoint20 = 0;
        double minJoint21 = 0;

        #endregion

        public AssessmentROM()
        {
            this.InitializeComponent();

            // Insert code required on object creation below this point.
            # region speech to control start and stop of assessment
            _recognizer = new SpeechRecognitionEngine();
            _recognizer.SetInputToDefaultAudioDevice();

            // Specify the exact words that the engine will try to recognize.
            Choices choices = new Choices();
            choices.Add("start");
            choices.Add("stop");

            // Create and load a Grammar using the Choices above.
            GrammarBuilder grBuilder = new GrammarBuilder(choices);
            Grammar grammar = new Grammar(grBuilder);
            _recognizer.LoadGrammar(grammar);

            // Create the event handler
            _recognizer.SpeechRecognized += new EventHandler<SpeechRecognizedEventArgs>(_recognizer_SpeechRecognized);

            // Start speech recognition
            // RecognizeMode.Single: The recognition process will stop after the first recognition.
            // RecognizeMode.Multiple: The recognition process will not stop after the first recognition.
            _recognizer.RecognizeAsync(RecognizeMode.Multiple);

            #endregion

            #region declare datagrid to display ROM's value
            ds = new DataSet();
            dt = new DataTable();
            ds.Tables.Add(dt);

            DataColumn cl = new DataColumn("Joint", typeof(string));
            cl.MaxLength = 100;
            dt.Columns.Add(cl);

            cl = new DataColumn("Max Angle", typeof(string));
            cl.MaxLength = 100;
            dt.Columns.Add(cl);

            cl = new DataColumn("Min Angle", typeof(string));
            cl.MaxLength = 100;
            dt.Columns.Add(cl);
            #endregion
        }

        private void btnBack_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                nui.Uninitialize();
            }
            catch (Exception)
            {
            }
            uploadToAzure = false;
            NavigationService.GoBack();
        }

        private void btnStart_Click(object sender, RoutedEventArgs e)
        {
            //start assessment
            initalizeStartKinectSDK();
        }

        //int sessionID;
        private void btnEnd_Click(object sender, RoutedEventArgs e)
        {
            //end assessment
            if (uploadToAzure == false)
            {
                try
                {
                    nui.Uninitialize();
                }
                catch (Exception)
                {
                }
                //Create a new session after assessment is completed
                svc.createNewSessionCompleted += new EventHandler<tara_wcf.createNewSessionCompletedEventArgs>(svc_createNewSessionCompleted);
                svc.createNewSessionAsync(MainPage.patientID, 10);

                uploadToAzure = true;
            }
        }

        bool uploadToAzure = false;
        void svc_createNewSessionCompleted(object sender, tara_wcf.createNewSessionCompletedEventArgs e)
        {
            if (e.Error == null && e.Result != null)
            {
                if (uploadToAzure == true)
                {
                    try
                    {
                        int sessionID = Convert.ToInt16(e.Result);
                        svc.createNewGamePlayCompleted += new EventHandler<tara_wcf.createNewGamePlayCompletedEventArgs>(svc_createNewGamePlayCompleted);
                        //Create the data in the database with the created new session
                        svc.createNewGamePlayAsync(sessionID, "2", "Max Angle Y", maxJoint2.ToString());
                        svc.createNewGamePlayAsync(sessionID, "2", "Min Angle Y", minJoint2.ToString());
                        svc.createNewGamePlayAsync(sessionID, "2", "Max Angle Z", maxJoint14.ToString());
                        svc.createNewGamePlayAsync(sessionID, "2", "Min Angle Z", minJoint14.ToString());
                        svc.createNewGamePlayAsync(sessionID, "2", "Max Angle X", maxJoint15.ToString());
                        svc.createNewGamePlayAsync(sessionID, "2", "Min Angle X", minJoint15.ToString());

                        svc.createNewGamePlayAsync(sessionID, "4", "Max Angle Z", maxJoint4.ToString());
                        svc.createNewGamePlayAsync(sessionID, "4", "Min Angle Z", minJoint4.ToString());

                        svc.createNewGamePlayAsync(sessionID, "3", "Max Angle Y", maxJoint3.ToString());
                        svc.createNewGamePlayAsync(sessionID, "3", "Min Angle Y", minJoint3.ToString());
                        svc.createNewGamePlayAsync(sessionID, "3", "Max Angle Z", maxJoint17.ToString());
                        svc.createNewGamePlayAsync(sessionID, "3", "Min Angle Z", minJoint17.ToString());
                        svc.createNewGamePlayAsync(sessionID, "3", "Max Angle X", maxJoint16.ToString());
                        svc.createNewGamePlayAsync(sessionID, "3", "Min Angle X", minJoint16.ToString());

                        //svc.createNewGamePlayAsync(sessionID, 8, "4", "", "Max Angle", maxJoint4.ToString());
                        //svc.createNewGamePlayAsync(sessionID, 8, "4", "", "Min Angle", minJoint4.ToString());
                        svc.createNewGamePlayAsync(sessionID, "5", "Max Angle Z", maxJoint5.ToString());
                        svc.createNewGamePlayAsync(sessionID, "5", "Min Angle Z", minJoint5.ToString());
                        svc.createNewGamePlayAsync(sessionID, "8", "Max Angle Z", maxJoint8.ToString());
                        svc.createNewGamePlayAsync(sessionID, "8", "Min Angle Z", minJoint8.ToString());
                        svc.createNewGamePlayAsync(sessionID, "9", "Max Angle X", maxJoint9.ToString());
                        svc.createNewGamePlayAsync(sessionID, "9", "Min Angle X", minJoint9.ToString());
                        svc.createNewGamePlayAsync(sessionID, "9", "Max Angle Z", maxJoint19.ToString());
                        svc.createNewGamePlayAsync(sessionID, "9", "Min Angle Z", minJoint19.ToString());

                        svc.createNewGamePlayAsync(sessionID, "10", "Max Angle X", maxJoint10.ToString());
                        svc.createNewGamePlayAsync(sessionID, "10", "Min Angle X", minJoint10.ToString());
                        svc.createNewGamePlayAsync(sessionID, "10", "Max Angle Z", maxJoint21.ToString());
                        svc.createNewGamePlayAsync(sessionID, "10", "Min Angle Z", minJoint21.ToString());

                        svc.createNewGamePlayAsync(sessionID, "11", "Max Angle Z", maxJoint11.ToString());
                        svc.createNewGamePlayAsync(sessionID, "11", "Min Angle Z", minJoint11.ToString());
                        svc.createNewGamePlayAsync(sessionID, "12", "Max Angle Z", maxJoint12.ToString());
                        svc.createNewGamePlayAsync(sessionID, "12", "Min Angle Z", minJoint12.ToString());

                        canvasBody.Children.Clear();
                        imgFeed.Source = null;  //Stop the image stream
                        dgMeasurements.ItemsSource = null;
                        uploadToAzure = true;
                    }
                    catch (Exception) { }
                }
            }
        }

        void svc_createNewGamePlayCompleted(object sender, tara_wcf.createNewGamePlayCompletedEventArgs e)
        {
            //createNewGamePlayCount++;
            //if (createNewGamePlayCount == 18)
            //{
            //    //
            //    //try
            //    //{
            //    //    //redownload data
            //    //    patientSessionList = svc.retrieveSessionOfPatient(p.Uid);
            //    //}
            //    //catch (Exception) { }
            //    //svc.retrieveExeAssignedtoPatientCompleted += new EventHandler<ServiceReference2.retrieveExeAssignedtoPatientCompletedEventArgs>(svc_retrieveExeAssignedtoPatientCompleted);
            //    //svc.retrieveExeAssignedtoPatientAsync(p.Uid);
            //    //svc.retrievePatientProblemsCompleted += new EventHandler<ServiceReference2.retrievePatientProblemsCompletedEventArgs>(svc_retrievePatientProblemsCompleted);
            //    //svc.retrievePatientProblemsAsync(p.Uid);

            //}
        }

        private void initalizeStartKinectSDK()
        {
            //Uncommented out as it is too lag
            //try
            //{
            //    #region start 3rd party SDK
            //    allowedROMtoStart = false;
            //    savingROMresult = false;
            //    startShowed = false;
            //    dgMeasurements.ItemsSource = null;
            //    gotUser = false;
            //    initalizeAndstartKinect();

            //    #region resetData

            //    //maxJoint1 = 0;
            //    maxJoint2 = 0;
            //    maxJoint3 = 0;
            //    maxJoint4 = 0;
            //    maxJoint5 = 0;
            //    //maxJoint6 = 0;
            //    //maxJoint7 = 0;
            //    maxJoint8 = 0;
            //    maxJoint9 = 0;
            //    maxJoint10 = 0;
            //    maxJoint11 = 0;
            //    maxJoint12 = 0;
            //    //maxJoint13 = 0;
            //    //maxJoint14 = 0;
            //    //minJoint1 = 0;
            //    minJoint2 = 0;
            //    minJoint3 = 0;
            //    minJoint4 = 0;
            //    minJoint5 = 0;
            //    //minJoint6 = 0;
            //    //minJoint7 = 0;
            //    minJoint8 = 0;
            //    minJoint9 = 0;
            //    minJoint10 = 0;
            //    minJoint11 = 0;
            //    minJoint12 = 0;
            //    //minJoint13 = 0;
            //    //minJoint14 = 0;

            //    #endregion

            //    #endregion
            //}
            //catch (Exception e)
            //{
            //Use Microsoft Official Beta SDK if 3rd Party SDK is not installed
            nui = new Runtime();
            uploadToAzure = false;
            try
            {
                nui.Initialize(RuntimeOptions.UseDepthAndPlayerIndex | RuntimeOptions.UseSkeletalTracking | RuntimeOptions.UseColor);
            }
            catch (InvalidOperationException)
            {
                System.Windows.MessageBox.Show("Runtime initialization failed. Please make sure Kinect device is plugged in.");
                return;
            }
            catch (Exception)
            {

            }

            try
            {
                nui.VideoStream.Open(ImageStreamType.Video, 2, ImageResolution.Resolution1280x1024, ImageType.Color);
                nui.DepthStream.Open(ImageStreamType.Depth, 2, ImageResolution.Resolution320x240, ImageType.DepthAndPlayerIndex);
            }
            catch (InvalidOperationException)
            {
                System.Windows.MessageBox.Show("Failed to open stream. Please make sure to specify a supported image type and resolution.");
                return;
            }
            lastTime = DateTime.Now;

            nui.DepthFrameReady += new EventHandler<ImageFrameReadyEventArgs>(nui_DepthFrameReady);
            nui.SkeletonFrameReady += new EventHandler<SkeletonFrameReadyEventArgs>(nui_SkeletonFrameReady);
            nui.VideoFrameReady += new EventHandler<ImageFrameReadyEventArgs>(nui_ColorFrameReady);
            //}
        }

        #region offical kinect sdk methods


        // Converts a 16-bit grayscale depth frame which includes player indexes into a 32-bit frame
        // that displays different players in different colors
        byte[] convertDepthFrame(byte[] depthFrame16)
        {
            int player = 0;
            for (int i16 = 0, i32 = 0; i16 < depthFrame16.Length && i32 < depthFrame32.Length; i16 += 2, i32 += 4)
            {
                player = depthFrame16[i16] & 0x07;
                int realDepth = (depthFrame16[i16 + 1] << 5) | (depthFrame16[i16] >> 3);
                // transform 13-bit depth information into an 8-bit intensity appropriate
                // for display (we disregard information in most significant bit)
                byte intensity = (byte)(255 - (255 * realDepth / 0x0fff));

                depthFrame32[i32 + RED_IDX] = 0;
                depthFrame32[i32 + GREEN_IDX] = 0;
                depthFrame32[i32 + BLUE_IDX] = 0;

                // choose different display colors based on player
                switch (player)
                {
                    case 0:
                        depthFrame32[i32 + RED_IDX] = (byte)(intensity / 2);
                        depthFrame32[i32 + GREEN_IDX] = (byte)(intensity / 2);
                        depthFrame32[i32 + BLUE_IDX] = (byte)(intensity / 2);
                        break;
                    case 1:
                        depthFrame32[i32 + RED_IDX] = intensity;
                        break;
                    case 2:
                        depthFrame32[i32 + GREEN_IDX] = intensity;
                        break;
                    case 3:
                        depthFrame32[i32 + RED_IDX] = (byte)(intensity / 4);
                        depthFrame32[i32 + GREEN_IDX] = (byte)(intensity);
                        depthFrame32[i32 + BLUE_IDX] = (byte)(intensity);
                        break;
                    case 4:
                        depthFrame32[i32 + RED_IDX] = (byte)(intensity);
                        depthFrame32[i32 + GREEN_IDX] = (byte)(intensity);
                        depthFrame32[i32 + BLUE_IDX] = (byte)(intensity / 4);
                        break;
                    case 5:
                        depthFrame32[i32 + RED_IDX] = (byte)(intensity);
                        depthFrame32[i32 + GREEN_IDX] = (byte)(intensity / 4);
                        depthFrame32[i32 + BLUE_IDX] = (byte)(intensity);
                        break;
                    case 6:
                        depthFrame32[i32 + RED_IDX] = (byte)(intensity / 2);
                        depthFrame32[i32 + GREEN_IDX] = (byte)(intensity / 2);
                        depthFrame32[i32 + BLUE_IDX] = (byte)(intensity);
                        break;
                    case 7:
                        depthFrame32[i32 + RED_IDX] = (byte)(255 - intensity);
                        depthFrame32[i32 + GREEN_IDX] = (byte)(255 - intensity);
                        depthFrame32[i32 + BLUE_IDX] = (byte)(255 - intensity);
                        break;
                }
            }
            //label3.Content = player.ToString();
            return depthFrame32;
        }

        void nui_DepthFrameReady(object sender, ImageFrameReadyEventArgs e)
        {
            GenerateColoredBytes(e.ImageFrame);

            PlanarImage Image = e.ImageFrame.Image;
            byte[] convertedDepthFrame = convertDepthFrame(Image.Bits);

            //depth.Source = BitmapSource.Create(
            //    Image.Width, Image.Height, 96, 96, PixelFormats.Bgr32, null, convertedDepthFrame, Image.Width * 4);

            ++totalFrames;
            DateTime cur = DateTime.Now;
            if (cur.Subtract(lastTime) > TimeSpan.FromSeconds(1))
            {
                int frameDiff = totalFrames - lastFrames;
                lastFrames = totalFrames;
                lastTime = cur;
                //frameRate.Text = frameDiff.ToString() + " fps";
            }
        }

        private byte[] GenerateColoredBytes(ImageFrame imageFrame)
        {
            int height = imageFrame.Image.Height;
            int width = imageFrame.Image.Width;

            //Depth data for each pixel
            Byte[] depthData = imageFrame.Image.Bits;

            //colorFrame contains color information for all pixels in image
            //Height x Width x 4 (Red, Green, Blue, empty byte)
            Byte[] colorFrame = new byte[imageFrame.Image.Height * imageFrame.Image.Width * 4];

            //Bgr32  - Blue, Green, Red, empty byte
            //Bgra32 - Blue, Green, Red, transparency 
            //You must set transparency for Bgra as .NET defaults a byte to 0 = fully transparent

            //hardcoded locations to Blue, Green, Red (BGR) index positions       
            const int BlueIndex = 0;
            const int GreenIndex = 1;
            const int RedIndex = 2;

            var depthIndex = 0;
            for (var y = 0; y < height; y++)
            {
                var heightOffset = y * width;

                for (var x = 0; x < width; x++)
                {
                    var index = ((width - x - 1) + heightOffset) * 4;
                    //label3.Content = GetPlayerIndex(depthData[depthIndex]).ToString();
                    //var distance = GetDistance(depthData[depthIndex], depthData[depthIndex + 1]);
                    var distance = GetDistanceWithPlayerIndex(depthData[depthIndex], depthData[depthIndex + 1]);

                    if (distance <= 900)
                    {
                        //we are very close
                        colorFrame[index + BlueIndex] = 255;
                        colorFrame[index + GreenIndex] = 0;
                        colorFrame[index + RedIndex] = 0;
                    }
                    else if (distance > 900 && distance < 2000)
                    {
                        //we are a bit further away
                        colorFrame[index + BlueIndex] = 0;
                        colorFrame[index + GreenIndex] = 255;
                        colorFrame[index + RedIndex] = 0;
                    }
                    else if (distance > 2000)
                    {
                        //we are the farthest
                        colorFrame[index + BlueIndex] = 0;
                        colorFrame[index + GreenIndex] = 0;
                        colorFrame[index + RedIndex] = 255;
                    }

                    //Color a player
                    if (GetPlayerIndex(depthData[depthIndex]) > 0)
                    {
                        //we are the farthest
                        colorFrame[index + BlueIndex] = 0;
                        colorFrame[index + GreenIndex] = 255;
                        colorFrame[index + RedIndex] = 255;
                    }

                    //jump two bytes at a time
                    depthIndex += 2;
                }
            }
            return colorFrame;
        }

        private static int GetPlayerIndex(byte firstFrame)
        {
            //returns 0 = no player, 1 = 1st player, 2 = 2nd player...
            return (int)firstFrame & 7;
        }

        private int GetDistanceWithPlayerIndex(byte firstFrame, byte secondFrame)
        {
            //offset by 3 in first byte to get value after player index 
            int distance = (int)(firstFrame >> 3 | secondFrame << 5);
            return distance;
        }

        private Point getDisplayPosition(Joint joint)
        {
            float depthX, depthY;
            nui.SkeletonEngine.SkeletonToDepthImage(joint.Position, out depthX, out depthY);
            depthX = Math.Max(0, Math.Min(depthX * 320, 320));  //convert to 320, 240 space
            depthY = Math.Max(0, Math.Min(depthY * 240, 240));  //convert to 320, 240 space
            int colorX, colorY;
            ImageViewArea iv = new ImageViewArea();
            // only ImageResolution.Resolution640x480 is supported at this point
            nui.NuiCamera.GetColorPixelCoordinatesFromDepthPixel(ImageResolution.Resolution640x480, iv, (int)depthX, (int)depthY, (short)0, out colorX, out colorY);

            // map back to canvasBody.Width & canvasBody.Height
            return new Point((int)(canvasBody.Width * colorX / 640.0), (int)(canvasBody.Height * colorY / 480));
        }

        Polyline getBodySegment(Microsoft.Research.Kinect.Nui.JointsCollection joints, Brush brush, params JointID[] ids)
        {
            PointCollection points = new PointCollection(ids.Length);
            for (int i = 0; i < ids.Length; ++i)
            {
                points.Add(getDisplayPosition(joints[ids[i]]));
            }
            Polyline polyline = new Polyline();
            polyline.Points = points;
            polyline.Stroke = brush;
            polyline.StrokeThickness = 10;
            return polyline;
        }

        DataTable dt;
        DataSet ds;
        double now = 0;
        void nui_SkeletonFrameReady(object sender, SkeletonFrameReadyEventArgs e)
        {
            #region joint rom
            ds = new DataSet();
            dt = new DataTable();
            ds.Tables.Add(dt);

            DataColumn cl = new DataColumn("Joint", typeof(string));
            cl.MaxLength = 100;
            dt.Columns.Add(cl);

            cl = new DataColumn("Max Angle", typeof(string));
            cl.MaxLength = 100;
            dt.Columns.Add(cl);

            cl = new DataColumn("Min Angle", typeof(string));
            cl.MaxLength = 100;
            dt.Columns.Add(cl);

            SkeletonFrame skeletonFrame = e.SkeletonFrame;
            int iSkeleton = 0;
            #region brushes
            Brush[] brushes = new Brush[6];
            brushes[0] = new SolidColorBrush(Color.FromRgb(255, 0, 0));
            brushes[1] = new SolidColorBrush(Color.FromRgb(0, 255, 0));
            brushes[2] = new SolidColorBrush(Color.FromRgb(64, 255, 255));
            brushes[3] = new SolidColorBrush(Color.FromRgb(255, 255, 64));
            brushes[4] = new SolidColorBrush(Color.FromRgb(255, 64, 255));
            brushes[5] = new SolidColorBrush(Color.FromRgb(128, 128, 255));
            #endregion
            canvasBody.Children.Clear();

            //Detect only the first skeleton
            SkeletonData data = (from s in skeletonFrame.Skeletons
                                 where s.TrackingState == SkeletonTrackingState.Tracked
                                 select s).FirstOrDefault();// Display only one set of s

            if (data != null)
            {
                // Draw bones
                Brush brush = brushes[iSkeleton % brushes.Length];
                brush = brushes[iSkeleton % brushes.Length];
                canvasBody.Children.Add(getBodySegment(data.Joints, brush, JointID.HipCenter, JointID.Spine, JointID.ShoulderCenter, JointID.Head));
                canvasBody.Children.Add(getBodySegment(data.Joints, brush, JointID.ShoulderCenter, JointID.ShoulderLeft, JointID.ElbowLeft, JointID.WristLeft, JointID.HandLeft));
                canvasBody.Children.Add(getBodySegment(data.Joints, brush, JointID.ShoulderCenter, JointID.ShoulderRight, JointID.ElbowRight, JointID.WristRight, JointID.HandRight));
                canvasBody.Children.Add(getBodySegment(data.Joints, brush, JointID.HipCenter, JointID.HipLeft, JointID.KneeLeft, JointID.AnkleLeft, JointID.FootLeft));
                canvasBody.Children.Add(getBodySegment(data.Joints, brush, JointID.HipCenter, JointID.HipRight, JointID.KneeRight, JointID.AnkleRight, JointID.FootRight));

                // Draw joints
                foreach (Joint joint in data.Joints)
                {
                    Point jointPos = getDisplayPosition(joint);
                    Line jointLine = new Line();
                    jointLine.X1 = jointPos.X - 3;
                    jointLine.X2 = jointLine.X1 + 6;
                    jointLine.Y1 = jointLine.Y2 = jointPos.Y;
                    jointLine.Stroke = jointColors[joint.ID];
                    jointLine.StrokeThickness = 6;
                    canvasBody.Children.Add(jointLine);
                }

                //}
                iSkeleton++;

                float HandLeftX = data.Joints[JointID.HandLeft].Position.X;
                if (HandLeftX != 0)
                {
                    #region vector3d
                    float HandLeftY = data.Joints[JointID.HandLeft].Position.Y;
                    float HandLeftZ = data.Joints[JointID.HandLeft].Position.Z;
                    Vector3D handLeftVector = new Vector3D(HandLeftX, HandLeftY, HandLeftZ);
                    handLeftVector.Normalize();

                    float ElbowLeftX = data.Joints[JointID.ElbowLeft].Position.X;
                    float ElbowLeftY = data.Joints[JointID.ElbowLeft].Position.Y;
                    float ElbowLeftZ = data.Joints[JointID.ElbowLeft].Position.Z;
                    Vector3D ElbowLeftEVector = new Vector3D(ElbowLeftX, ElbowLeftY, ElbowLeftZ);
                    ElbowLeftEVector.Normalize();

                    float ShoulderLeftX = data.Joints[JointID.ShoulderLeft].Position.X;
                    float ShoulderLeftY = data.Joints[JointID.ShoulderLeft].Position.Y;
                    float ShoulderLeftZ = data.Joints[JointID.ShoulderLeft].Position.Z;
                    Vector3D ShoulderLeftVector = new Vector3D(ShoulderLeftX, ShoulderLeftY, ShoulderLeftZ);
                    ShoulderLeftVector.Normalize();

                    float headX = data.Joints[JointID.Head].Position.X;
                    float headY = data.Joints[JointID.Head].Position.Y;
                    float headZ = data.Joints[JointID.Head].Position.Z;
                    Vector3D HeadVector = new Vector3D(headX, headY, headZ);
                    HeadVector.Normalize();
                    Color userColor = Colors.Black;
                    if (2500 < headZ)
                    {
                        if (headZ < 3000)
                        {
                            userColor = (Color)ColorConverter.ConvertFromString("#FFFFD700");
                        }
                    }

                    float ShoulderCenterX = data.Joints[JointID.ShoulderCenter].Position.X;
                    float ShoulderCenterY = data.Joints[JointID.ShoulderCenter].Position.Y;
                    float ShoulderCenterZ = data.Joints[JointID.ShoulderCenter].Position.Z;
                    Vector3D ShoulderCenterVector = new Vector3D(ShoulderCenterX, ShoulderCenterY, ShoulderCenterZ);
                    ShoulderCenterVector.Normalize();

                    float ShoulderRightX = data.Joints[JointID.ShoulderRight].Position.X;
                    float ShoulderRightY = data.Joints[JointID.ShoulderRight].Position.Y;
                    float ShoulderRightZ = data.Joints[JointID.ShoulderRight].Position.Z;
                    Vector3D ShoulderRightVector = new Vector3D(ShoulderRightX, ShoulderRightY, ShoulderRightZ);
                    ShoulderRightVector.Normalize();
                    #region invis arm
                    float fakeRightShoulderX = data.Joints[JointID.ShoulderRight].Position.X;
                    float fakeRightShoulderY = data.Joints[JointID.ShoulderRight].Position.Y;
                    float fakeRightShoulderZ = data.Joints[JointID.ShoulderRight].Position.Z - 0.5f;
                    Vector3D fakeRightShoulder3D = new Vector3D(fakeRightShoulderX, fakeRightShoulderY, fakeRightShoulderZ - 0.5f);
                    fakeRightShoulder3D.Normalize();

                    float fakeRightShoulderXAxis3 = data.Joints[JointID.ShoulderRight].Position.X + 0.5f;
                    float fakeRightShoulderYAxis3 = data.Joints[JointID.ShoulderRight].Position.Y;
                    float fakeRightShoulderZAxis3 = data.Joints[JointID.ShoulderRight].Position.Z;
                    Vector3D fakeRightShoulder3DAxis3 = new Vector3D(fakeRightShoulderXAxis3 + 0.5f, fakeRightShoulderYAxis3, fakeRightShoulderZAxis3);
                    fakeRightShoulder3DAxis3.Normalize();

                    float fakeLeftShoulderX = data.Joints[JointID.ShoulderLeft].Position.X;
                    float fakeLeftShoulderY = data.Joints[JointID.ShoulderLeft].Position.Y;
                    float fakeLeftShoulderZ = data.Joints[JointID.ShoulderLeft].Position.Z - 0.5f;
                    Vector3D fakeLeftShoulder3D = new Vector3D(fakeLeftShoulderX, fakeLeftShoulderY, fakeLeftShoulderZ - 0.5f);
                    fakeLeftShoulder3D.Normalize();

                    float fakeLeftShoulderXAxis3 = data.Joints[JointID.ShoulderLeft].Position.X - 0.5f;
                    float fakeLeftShoulderYAxis3 = data.Joints[JointID.ShoulderLeft].Position.Y;
                    float fakeLeftShoulderZAxis3 = data.Joints[JointID.ShoulderLeft].Position.Z;
                    Vector3D fakeLeftShoulder3DAxis3 = new Vector3D(fakeLeftShoulderXAxis3 - 0.5f, fakeLeftShoulderYAxis3, fakeLeftShoulderZAxis3);
                    fakeLeftShoulder3DAxis3.Normalize();

                    #endregion

                    float HandRightX = data.Joints[JointID.HandRight].Position.X;
                    float HandRightY = data.Joints[JointID.HandRight].Position.Y;
                    float HandRightZ = data.Joints[JointID.HandRight].Position.Z;
                    Vector3D HandRightVector = new Vector3D(HandRightX, HandRightY, HandRightZ);
                    HandRightVector.Normalize();

                    float ElbowRightX = data.Joints[JointID.ElbowRight].Position.X;
                    float ElbowRightY = data.Joints[JointID.ElbowRight].Position.Y;
                    float ElbowRightZ = data.Joints[JointID.ElbowRight].Position.Z;
                    Vector3D ElbowRightVector = new Vector3D(ElbowRightX, ElbowRightY, ElbowRightZ);
                    ElbowRightVector.Normalize();

                    float HipCenterX = data.Joints[JointID.HipCenter].Position.X;
                    float HipCenterY = data.Joints[JointID.HipCenter].Position.Y;
                    float HipCenterZ = data.Joints[JointID.HipCenter].Position.Z;
                    Vector3D HipCenterVector = new Vector3D(HipCenterX, HipCenterY, HipCenterZ);
                    HipCenterVector.Normalize();

                    float HipLeftX = data.Joints[JointID.HipLeft].Position.X;
                    float HipLeftY = data.Joints[JointID.HipLeft].Position.Y;
                    float HipLeftZ = data.Joints[JointID.HipLeft].Position.Z;
                    Vector3D HipLeftVector = new Vector3D(HipLeftX, HipLeftY, HipLeftZ);
                    HipLeftVector.Normalize();

                    float KneeLeftX = data.Joints[JointID.KneeLeft].Position.X;
                    float KneeLeftY = data.Joints[JointID.KneeLeft].Position.Y;
                    float KneeLeftZ = data.Joints[JointID.KneeLeft].Position.Z;
                    Vector3D KneeLeftVector = new Vector3D(KneeLeftX, KneeLeftY, KneeLeftZ);
                    KneeLeftVector.Normalize();

                    float FootLeftX = data.Joints[JointID.FootLeft].Position.X;
                    float FootLeftY = data.Joints[JointID.FootLeft].Position.Y;
                    float FootLeftZ = data.Joints[JointID.FootLeft].Position.Z;
                    Vector3D FootLeftVector = new Vector3D(FootLeftX, FootLeftY, FootLeftZ);
                    FootLeftVector.Normalize();

                    float HipRightX = data.Joints[JointID.HipRight].Position.X;
                    float HipRightY = data.Joints[JointID.HipRight].Position.Y;
                    float HipRightZ = data.Joints[JointID.HipRight].Position.Z;
                    Vector3D HipRightVector = new Vector3D(HipRightX, HipRightY, HipRightZ);
                    HipRightVector.Normalize();
                    #region invis hip
                    float fakeRightHipX = data.Joints[JointID.HipRight].Position.X;
                    float fakeRightHipY = data.Joints[JointID.HipRight].Position.Y;
                    float fakeRightHipZ = data.Joints[JointID.HipRight].Position.Z - 0.5f;
                    Vector3D fakeRightHipX3D = new Vector3D(fakeRightHipX, fakeRightHipY, fakeRightHipZ - 0.5f);
                    fakeRightHipX3D.Normalize();

                    float fakeRightHipXAxis3 = data.Joints[JointID.HipRight].Position.X + 0.5f;
                    float fakeRightHipYAxis3 = data.Joints[JointID.HipRight].Position.Y;
                    float fakeRightHipZAxis3 = data.Joints[JointID.HipRight].Position.Z;
                    Vector3D fakeRightHipX3DAxis3 = new Vector3D(fakeRightHipX + 0.5f, fakeRightHipY, fakeRightHipZ);
                    fakeRightHipX3DAxis3.Normalize();

                    float fakeLeftHipX = data.Joints[JointID.HipLeft].Position.X;
                    float fakeLeftHipY = data.Joints[JointID.HipLeft].Position.Y;
                    float fakeLeftHipZ = data.Joints[JointID.HipLeft].Position.Z - 0.5f;
                    Vector3D fakeLeftHipX3D = new Vector3D(fakeLeftHipX, fakeLeftHipY, fakeLeftHipZ - 0.5f);
                    fakeLeftHipX3D.Normalize();

                    float fakeLeftHipXAxis3 = data.Joints[JointID.HipLeft].Position.X + 0.5f;
                    float fakeLeftHipYAxis3 = data.Joints[JointID.HipLeft].Position.Y;
                    float fakeLeftHipZAxis3 = data.Joints[JointID.HipLeft].Position.Z;
                    Vector3D fakeLeftHipX3DAxis3 = new Vector3D(fakeLeftHipX + 0.5f, fakeLeftHipY, fakeLeftHipZ);
                    fakeLeftHipX3DAxis3.Normalize();
                    #endregion

                    float KneeRightX = data.Joints[JointID.KneeRight].Position.X;
                    float KneeRightY = data.Joints[JointID.KneeRight].Position.Y;
                    float KneeRightZ = data.Joints[JointID.KneeRight].Position.Z;
                    Vector3D KneeRightVector = new Vector3D(KneeRightX, KneeRightY, KneeRightZ);
                    KneeRightVector.Normalize();

                    float FootRightX = data.Joints[JointID.FootRight].Position.X;
                    float FootRightY = data.Joints[JointID.FootRight].Position.Y;
                    float FootRightZ = data.Joints[JointID.FootRight].Position.Z;
                    Vector3D FootRightVector = new Vector3D(FootRightX, FootRightY, FootRightZ);
                    FootRightVector.Normalize();
                    #endregion

                    ds.Clear();
                    #region calculate angle
                    #region LeftShoulder X
                    Vector3D leftShoulderV1Axis3 = ElbowLeftEVector - ShoulderLeftVector;
                    Vector3D leftShoulderV2Axis3 = fakeLeftShoulder3DAxis3 - ShoulderLeftVector;
                    double leftShoulderAngleAxis3 = Vector3D.AngleBetween(leftShoulderV1Axis3, leftShoulderV2Axis3);
                    now = Math.Round(leftShoulderAngleAxis3, 3);
                    if (now != double.NaN)
                    {
                        switch (maxJoint15 == 0 && minJoint15 == 0)
                        {
                            case true:
                                maxJoint15 = now;
                                minJoint15 = now;
                                break;
                        }

                        switch (now > maxJoint15)
                        {
                            case true:
                                maxJoint15 = now;
                                break;
                        }
                        switch (now < minJoint15)
                        {
                            case true:
                                minJoint15 = now;
                                break;
                        }

                        DataRow rw = dt.NewRow();
                        dt.Rows.Add(rw);
                        rw["Joint"] = "Left Shoulder X";
                        rw["Max Angle"] = maxJoint15.ToString();
                        rw["Min Angle"] = minJoint15.ToString();

                    }
                    #endregion
                    #region Left Shoulders Y

                    Vector3D leftShoulderV1 = ElbowLeftEVector - ShoulderLeftVector;
                    Vector3D leftShoulderV2 = HipLeftVector - ShoulderLeftVector;
                    double leftShoulderAngle = Vector3D.AngleBetween(leftShoulderV1, leftShoulderV2);
                    now = Math.Round(leftShoulderAngle, 3);
                    if (now != double.NaN)
                    {
                        switch (maxJoint2 == 0 && minJoint2 == 0)
                        {
                            case true:
                                maxJoint2 = now;
                                minJoint2 = now;
                                break;
                        }

                        switch (now > maxJoint2)
                        {
                            case true:
                                maxJoint2 = now;
                                break;
                        }
                        switch (now < minJoint2)
                        {
                            case true:
                                minJoint2 = now;
                                break;
                        }

                        DataRow rw = dt.NewRow();
                        dt.Rows.Add(rw);
                        rw["Joint"] = "Left Shoulder Y";
                        rw["Max Angle"] = maxJoint2.ToString();
                        rw["Min Angle"] = minJoint2.ToString(); ;
                    }


                    #endregion
                    #region LeftShoulder Z
                    Vector3D leftShoulderV1Axis2 = ElbowLeftEVector - ShoulderLeftVector;
                    Vector3D leftShoulderV2Axis2 = fakeLeftShoulder3D - ShoulderLeftVector;
                    double leftShoulderAngleAxis2 = Vector3D.AngleBetween(leftShoulderV1Axis2, leftShoulderV2Axis2);
                    now = Math.Round(leftShoulderAngleAxis2, 3);
                    if (now != double.NaN)
                    {
                        switch (maxJoint14 == 0 && minJoint14 == 0)
                        {
                            case true:
                                maxJoint14 = now;
                                minJoint14 = now;
                                break;
                        }

                        switch (now > maxJoint14)
                        {
                            case true:
                                maxJoint14 = now;
                                break;
                        }
                        switch (now < minJoint14)
                        {
                            case true:
                                minJoint14 = now;
                                break;
                        }

                        DataRow rw = dt.NewRow();
                        dt.Rows.Add(rw);
                        rw["Joint"] = "Left Shoulder Z";
                        rw["Max Angle"] = maxJoint14.ToString();
                        rw["Min Angle"] = minJoint14.ToString();

                    }
                    #endregion

                    #region Right Shoulder X
                    Vector3D rightShoulderV1Axis2 = ElbowRightVector - ShoulderRightVector;
                    Vector3D rightShoulderV2Axis2 = fakeRightShoulder3D - ShoulderRightVector;
                    double rightShoulderAngleAxis2 = Vector3D.AngleBetween(rightShoulderV1Axis2, rightShoulderV2Axis2);
                    now = Math.Round(rightShoulderAngleAxis2, 3);
                    if (now != double.NaN)
                    {
                        switch (maxJoint16 == 0 && minJoint16 == 0)
                        {
                            case true:
                                maxJoint16 = now;
                                minJoint16 = now;
                                break;

                        }

                        switch (now > maxJoint16)
                        {
                            case true:
                                maxJoint16 = now;
                                break;
                        }
                        switch (now < minJoint16)
                        {
                            case true:
                                minJoint16 = now;
                                break;
                        }

                        DataRow rw = dt.NewRow();
                        dt.Rows.Add(rw);
                        rw["Joint"] = "Right Shoulder X";
                        rw["Max Angle"] = maxJoint16.ToString();
                        rw["Min Angle"] = minJoint16.ToString();
                    }
                    #endregion
                    #region Right Shoulders Y

                    Vector3D rightShoulderV1 = ElbowRightVector - ShoulderRightVector;
                    Vector3D rightShoulderV2 = HipRightVector - ShoulderRightVector;
                    double rightShoulderAngle = Vector3D.AngleBetween(rightShoulderV1, rightShoulderV2);
                    now = Math.Round(rightShoulderAngle, 3);
                    if (now != double.NaN)
                    {
                        switch (maxJoint3 == 0 && minJoint3 == 0)
                        {
                            case true:
                                maxJoint3 = now;
                                minJoint3 = now;
                                break;
                        }

                        switch (now > maxJoint3)
                        {
                            case true:
                                maxJoint3 = now;
                                break;
                        }
                        switch (now < minJoint3)
                        {
                            case true:
                                minJoint3 = now;
                                break;
                        }

                        DataRow rw1 = dt.NewRow();
                        dt.Rows.Add(rw1);
                        rw1["Joint"] = "Right Shoulder Y";
                        rw1["Max Angle"] = maxJoint3.ToString();
                        rw1["Min Angle"] = minJoint3.ToString(); ;
                    }
                    #endregion
                    #region Right Shoulder Z
                    Vector3D rightShoulderV1Axis3 = ElbowRightVector - ShoulderRightVector;
                    Vector3D rightShoulderV2Axis3 = fakeRightShoulder3DAxis3 - ShoulderRightVector;
                    double rightShoulderAngleAxis3 = Vector3D.AngleBetween(rightShoulderV1Axis3, rightShoulderV2Axis3);
                    now = Math.Round(rightShoulderAngleAxis3, 3);
                    if (now != double.NaN)
                    {
                        switch (maxJoint17 == 0 && minJoint17 == 0)
                        {
                            case true:
                                maxJoint17 = now;
                                minJoint17 = now;
                                break;
                        }

                        switch (now > maxJoint17)
                        {
                            case true:
                                maxJoint17 = now;
                                break;
                        }
                        switch (now < minJoint17)
                        {
                            case true:
                                minJoint17 = now;
                                break;
                        }

                        DataRow rw = dt.NewRow();
                        dt.Rows.Add(rw);
                        rw["Joint"] = "Right Shoulder Z";
                        rw["Max Angle"] = maxJoint17.ToString();
                        rw["Min Angle"] = minJoint17.ToString();

                    }
                    #endregion

                    #region leftElbow

                    Vector3D leftElbowV1 = ShoulderLeftVector - ElbowLeftEVector;
                    Vector3D leftElbowV2 = handLeftVector - ElbowLeftEVector;
                    double leftElbowAngle = Vector3D.AngleBetween(leftElbowV1, leftElbowV2);
                    now = Math.Round(leftElbowAngle, 3) + 5;
                    if (now != double.NaN)
                    {
                        switch (maxJoint4 == 0 && minJoint4 == 0)
                        {
                            case true:
                                maxJoint4 = now;
                                minJoint4 = now;
                                break;
                        }

                        switch (now > maxJoint4)
                        {
                            case true:
                                maxJoint4 = now;
                                break;
                        }
                        switch (now < minJoint4)
                        {
                            case true:
                                minJoint4 = now;
                                break;
                        }

                        DataRow rw2 = dt.NewRow();
                        dt.Rows.Add(rw2);
                        rw2["Joint"] = "Left Elbow";
                        rw2["Max Angle"] = maxJoint4.ToString();
                        rw2["Min Angle"] = minJoint4.ToString();
                    }
                    #endregion
                    #region rightElbow

                    Vector3D rightElbowV1 = ShoulderRightVector - ElbowRightVector;
                    Vector3D rightElbowV2 = HandRightVector - ElbowRightVector;
                    double rightElbowAngle = Vector3D.AngleBetween(rightElbowV1, rightElbowV2);
                    now = Math.Round(rightElbowAngle, 3);
                    if (now != double.NaN)
                    {
                        switch (maxJoint5 == 0 && minJoint5 == 0)
                        {
                            case true:
                                maxJoint5 = now;
                                minJoint5 = now;
                                break;
                        }

                        switch (now > maxJoint5)
                        {
                            case true:
                                maxJoint5 = now;
                                break;
                        }
                        switch (now < minJoint5)
                        {
                            case true:
                                minJoint5 = now;
                                break;
                        }

                        DataRow rw3 = dt.NewRow();
                        dt.Rows.Add(rw3);
                        rw3["Joint"] = "Right Elbow";
                        rw3["Max Angle"] = maxJoint5.ToString();
                        rw3["Min Angle"] = minJoint5.ToString();
                    }
                    #endregion

                    #region Torso

                    Vector3D spine = HipCenterVector - ShoulderCenterVector;
                    Vector3D leftShoulder = ShoulderLeftVector - ShoulderCenterVector;
                    double Torso = Vector3D.AngleBetween(spine, leftShoulder);
                    now = Math.Round(Torso, 3);
                    if (now != double.NaN)
                    {
                        switch (maxJoint8 == 0 && minJoint8 == 0)
                        {
                            case true:
                                maxJoint8 = now;
                                minJoint8 = now;
                                break;
                        }

                        switch (now > maxJoint8)
                        {
                            case true:
                                maxJoint8 = now;
                                break;
                        }
                        switch (now < minJoint8)
                        {
                            case true:
                                minJoint8 = now;
                                break;
                        }

                        DataRow rw4 = dt.NewRow();
                        dt.Rows.Add(rw4);
                        rw4["Joint"] = "Waist";
                        rw4["Max Angle"] = maxJoint8.ToString();
                        rw4["Min Angle"] = minJoint8.ToString();
                    }
                    #endregion
                    #region Left hips Y

                    Vector3D leftHipV1 = KneeRightVector - HipLeftVector;
                    Vector3D leftHipV2 = KneeLeftVector - HipLeftVector;
                    double leftHipAngle = Vector3D.AngleBetween(leftHipV1, leftHipV2);
                    now = Math.Round(leftHipAngle, 3);
                    if (now != double.NaN)
                    {
                        switch (maxJoint9 == 0 && minJoint9 == 0)
                        {
                            case true:
                                maxJoint9 = now;
                                minJoint9 = now;
                                break;
                        }

                        switch (now > maxJoint9)
                        {
                            case true:
                                maxJoint9 = now;
                                break;
                        }
                        switch (now < minJoint9)
                        {
                            case true:
                                minJoint9 = now;
                                break;
                        }


                        DataRow rw5 = dt.NewRow();
                        dt.Rows.Add(rw5);
                        rw5["Joint"] = "Left Hip Y";
                        rw5["Max Angle"] = maxJoint9.ToString();
                        rw5["Min Angle"] = minJoint9.ToString();
                    }
                    #endregion
                    #region Left hips Z
                    Vector3D leftHipV1Axis3 = fakeLeftHipX3DAxis3 - HipLeftVector;
                    Vector3D leftHipV2Axis3 = KneeLeftVector - HipLeftVector;
                    double leftHipAngleAxis3 = Vector3D.AngleBetween(leftHipV1Axis3, leftHipV2Axis3);
                    now = Math.Round(leftHipAngleAxis3, 3);
                    if (now != double.NaN)
                    {
                        switch (maxJoint19 == 0 && minJoint19 == 0)
                        {
                            case true:
                                maxJoint19 = now;
                                minJoint19 = now;
                                break;
                        }

                        switch (now > maxJoint19)
                        {
                            case true:
                                maxJoint19 = now;
                                break;
                        }
                        switch (now < minJoint19)
                        {
                            case true:
                                minJoint19 = now;
                                break;
                        }

                        DataRow rw = dt.NewRow();
                        dt.Rows.Add(rw);
                        rw["Joint"] = "Left Hip Z";
                        rw["Max Angle"] = maxJoint19.ToString();
                        rw["Min Angle"] = minJoint19.ToString();
                    }
                    #endregion
                    #region Right hips Y

                    Vector3D rightHipV1 = KneeLeftVector - HipRightVector;
                    Vector3D rightHipV2 = KneeRightVector - HipRightVector;
                    double rightHipAngle = Vector3D.AngleBetween(rightHipV1, rightHipV2);
                    now = Math.Round(rightHipAngle, 3);
                    if (now != double.NaN)
                    {
                        switch (maxJoint10 == 0 && minJoint10 == 0)
                        {
                            case true:
                                maxJoint10 = now;
                                minJoint10 = now;
                                break;
                        }

                        switch (now > maxJoint10)
                        {
                            case true:
                                maxJoint10 = now;
                                break;
                        }
                        switch (now < minJoint10)
                        {
                            case true:
                                minJoint10 = now;
                                break;
                        }

                        DataRow rw6 = dt.NewRow();
                        dt.Rows.Add(rw6);
                        rw6["Joint"] = "Right Hip Y";
                        rw6["Max Angle"] = maxJoint10.ToString();
                        rw6["Min Angle"] = minJoint10.ToString();
                    }
                    #endregion
                    #region Right hips Z
                    Vector3D rightHipV1Axis3 = fakeRightHipX3DAxis3 - HipRightVector;
                    Vector3D rightHipV2Axis3 = KneeRightVector - HipRightVector;
                    double rightHipAngleAxis3 = Vector3D.AngleBetween(rightHipV1Axis3, rightHipV2Axis3);
                    now = Math.Round(rightHipAngleAxis3, 3);
                    if (now != double.NaN)
                    {
                        switch (maxJoint21 == 0 && minJoint21 == 0)
                        {
                            case true:
                                maxJoint21 = now;
                                minJoint21 = now;
                                break;
                        }

                        switch (now > maxJoint21)
                        {
                            case true:
                                maxJoint21 = now;
                                break;
                        }
                        switch (now < minJoint21)
                        {
                            case true:
                                minJoint21 = now;
                                break;
                        }

                        DataRow rw = dt.NewRow();
                        dt.Rows.Add(rw);
                        rw["Joint"] = "Right Hip Z";
                        rw["Max Angle"] = maxJoint21.ToString();
                        rw["Min Angle"] = minJoint21.ToString();
                    }
                    #endregion

                    #region leftknee

                    Vector3D leftKneeV1 = HipLeftVector - KneeLeftVector;
                    Vector3D leftKneeV2 = FootLeftVector - KneeLeftVector;
                    double leftKneeAngle = Vector3D.AngleBetween(leftKneeV1, leftKneeV2);
                    now = Math.Round(leftKneeAngle, 3);
                    if (now != double.NaN)
                    {
                        switch (maxJoint11 == 0 && minJoint11 == 0)
                        {
                            case true:
                                maxJoint11 = now;
                                minJoint11 = now;
                                break;
                        }

                        switch (now > maxJoint11)
                        {
                            case true:
                                maxJoint11 = now;
                                break;
                        }
                        switch (now < minJoint11)
                        {
                            case true:
                                minJoint11 = now;
                                break;
                        }

                        DataRow rw7 = dt.NewRow();
                        dt.Rows.Add(rw7);
                        rw7["Joint"] = "Left Knee";
                        rw7["Max Angle"] = maxJoint11.ToString();
                        rw7["Min Angle"] = minJoint11.ToString();
                    }
                    #endregion
                    #region rightknee

                    Vector3D rightKneeV1 = HipRightVector - KneeRightVector;
                    Vector3D rightKneeV2 = FootRightVector - KneeRightVector;
                    double rightKneeAngle = Vector3D.AngleBetween(rightKneeV1, rightKneeV2);
                    now = Math.Round(rightKneeAngle, 3);
                    if (now != double.NaN)
                    {
                        switch (maxJoint12 == 0 && minJoint12 == 0)
                        {
                            case true:
                                maxJoint12 = now;
                                minJoint12 = now;
                                break;
                        }

                        switch (now > maxJoint12)
                        {
                            case true:
                                maxJoint12 = now;
                                break;
                        }
                        switch (now < minJoint12)
                        {
                            case true:
                                minJoint12 = now;
                                break;
                        }

                        DataRow rw8 = dt.NewRow();
                        dt.Rows.Add(rw8);
                        rw8["Joint"] = "Right Knee";
                        rw8["Max Angle"] = maxJoint12.ToString();
                        rw8["Min Angle"] = minJoint12.ToString();
                    }
                    #endregion

                    #region display result
                    dgMeasurements.ItemsSource = null;  //Reset the datagrid
                    dgMeasurements.ItemsSource = ds.Tables[0].DefaultView;  //Populate the datagrid with max/min of each major joint
                    #endregion

                    #endregion

                    //Point jointPos = getDisplayPosition(data.Joints[JointID.Head]);
                    //DrawCircle((float)(jointPos.X * 0.95), (float)(jointPos.Y * 0.7), ((SolidColorBrush)brush).Color);
                }
            }
            #endregion
            //float depthX, depthY;
            //short depthZ;
            //nui.SkeletonEngine.SkeletonToDepthImage(data.Joints[JointID.HandLeft].Position, out depthX, out depthY, out depthZ);
            // for each canvasBody
        }

        void DrawCircle(float positionX, float positionY, Color color)
        {
            Ellipse ellipse = new Ellipse
            {
                Fill = new SolidColorBrush(color),
                Width = 30,
                Height = 30,
                Margin = new Thickness(positionX, positionY + 15, 0, 0)
            };

            canvasBody.Children.Add(ellipse);
        }

        void nui_ColorFrameReady(object sender, ImageFrameReadyEventArgs e)
        {
            // 32-bit per pixel, RGBA image
            PlanarImage Image = e.ImageFrame.Image;

            imgFeed.Source = BitmapSource.Create(
                Image.Width, Image.Height, 96, 96, PixelFormats.Bgr32, null, Image.Bits, Image.Width * Image.BytesPerPixel);
        }
        #endregion

        #region old sdk
        bool kinectStartedBefore = false;
        bool allowedROMtoStart = false;
        bool savingROMresult = false;
        bool BWstarted = false;
        bool xmlRead = false;
        private void initalizeAndstartKinect()
        {
            if (kinectStartedBefore == false)
            {
                try
                {
                    BWstarted = true;
                    _worker.DoWork += new DoWorkEventHandler(Worker_DoWork);
                    CompositionTarget.Rendering += new EventHandler(CompositionTarget_Rendering);
                    if (!xmlRead)
                    {
                        try
                        {
                            _skeleton = new NuiUserTracker("SamplesConfig.xml");
                            //_skeleton = new NuiUserTracker(xmlPath());
                        }
                        catch (AccessViolationException)
                        {
                        }
                        xmlRead = true;
                    }


                    //_skeleton = nuiUserTracker;
                    //_skeleton = new NuiUserTracker("D:\\Users\\Kyzer\\Documents\\Visual Studio 2010\\Projects\\Loader\\Loader\\SamplesConfig.xml");
                    //_skeleton.UserUpdated += new NuiUserTracker.UserUpdatedHandler(Skeleton_UserUpdated);
                    _skeleton.UsersUpdated += new NuiUserTracker.UserListUpdatedHandler(_skeleton_UsersUpdated);
                    //_skeleton.UserLost += new NuiUserTracker.UserUpdatedHandler(_skeleton_UserLost);
                    //_skeleton.UserFound += new EventHandler(_skeleton_UserFound);
                    //_skeleton.UserTracked += new NuiUserTracker.UserUpdatedHandler(_skeleton_UserTracked);
                    _worker.WorkerSupportsCancellation = true;

                }
                catch (Exception)
                {
                    stopKinect();
                }
                BWstarted = true;

                try
                {
                    _skeleton.Start();
                    _worker.RunWorkerAsync();

                }
                catch (Exception)
                {
                    throw new Exception();
                    //MessageBox.Show("An error has occured. Please restart the app");
                }
                kinectStartedBefore = true;
            }
            else
            {
                startKinect();
            }
        }
      
        #region nui.vision
        //private string status = "";
        //private int userFound = 0;
        //void _skeleton_UserTracked(object sender, NuiUserEventArgs e)
        //{
        //    if (status != "UserTracked")
        //    {
        //        Dispatcher.BeginInvoke((Action)delegate
        //        {
        //            status = "UserTracked";
        //        });
        //    }

        //}

        //void _skeleton_UserFound(object sender, EventArgs e)
        //{
        //    if (status != "UserFound")
        //    {
        //        if (userFound != 1)
        //        {
        //            Dispatcher.BeginInvoke((Action)delegate
        //            {
        //                status = "UserFound";
        //                userFound++;
        //                //lbl_k_status.Text = "User Found. Calibrate to start.";
        //            });
        //        }

        //    }                                                                                                                            
        //}

        //void _skeleton_UserLost(object sender, NuiUserEventArgs e)
        //{
        //    if (status != "UserLost")
        //    {
        //        Dispatcher.BeginInvoke((Action)delegate
        //        {
        //            status = "UserLost";
        //        });
        //    }
        //}
        #endregion
      
        #region variables
     
        NuiUserTracker _skeleton;
        BackgroundWorker _worker = new BackgroundWorker();
        Color[] _userColors = { Colors.Blue, Colors.Red, Colors.Green, Colors.DarkOrange, Colors.Pink, Colors.Black };
        bool gotUser = false;
        //double now = 0;
        int xmlCount = 0;
        bool startShowed = false;
        #endregion

        void Worker_DoWork(object sender, DoWorkEventArgs e)
        {
            if (BWstarted != false && _worker.CancellationPending == false)
            {
                Dispatcher.BeginInvoke((Action)delegate
                {
                    if (gotUser == false)
                    {
                        //panel_calibrate.Visibility = Visibility.Visible;
                        gotUser = false;
                    }
                    else
                    {
                        //panel_calibrate.Visibility = Visibility.Collapsed;
                        if (startShowed == false)
                        {
                            startShowed = true;
                            //sp_k_controlPanel_start.Visibility = Visibility.Visible;
                        }
                    }
                    try
                    {
                        try
                        {
                            imgFeed.Source = _skeleton.RawImage;
                            //imgCamera.Source = _skeleton.UserTrackingImage;
                        }
                        catch (NullReferenceException) { }
                    }
                    catch (Exception)
                    {
                        stopKinect();
                    }
                });
            }
        }

        void CompositionTarget_Rendering(object sender, EventArgs e)
        {
            if (_worker.CancellationPending)
            {
                if (BWstarted == false)
                {
                    //_worker.CancelAsync();
                    //_worker.Dispose();
                }
            }
            else
            {
                if (!_worker.IsBusy)
                {
                    _worker.RunWorkerAsync();
                }
            }
        }

        void _skeleton_UsersUpdated(object sender, NuiUserListEventArgs e)
        {
            Dispatcher.BeginInvoke((Action)delegate
            {
                canvasBody.Children.Clear();

                if (e.Users.Count() == 0)
                {
                    gotUser = false;
                    //panel_calibrate.Visibility = Visibility.Visible;
                }
                else
                {
                    gotUser = true;
                    //panel_calibrate.Visibility = Visibility.Collapsed;
                }


            });
            #region Joint ROM
            Dispatcher.BeginInvoke((Action)delegate
            {
                if (startShowed == false)
                {
                    startShowed = true;
                    //sp_k_startROM.Visibility = Visibility.Visible;
                }

                foreach (var user in e.Users)
                {
                    Color userColor = _userColors[user.Id - 1];

                    #region Get body parts coordinates

                    float headX = user.Head.X;
                    float headY = user.Head.Y;
                    float headZ = user.Head.Z;
                    if (2500 < headZ)
                    {
                        if (headZ < 3000)
                        {
                            userColor = (Color)ColorConverter.ConvertFromString("#FFFFD700");
                        }
                    }
                    Vector3D head3D = new Vector3D(user.Head.X, user.Head.Y, user.Head.Z);
                    head3D.Normalize();

                    float neckX = user.Neck.X;
                    float neckY = user.Neck.Y;
                    Vector3D neck3D = new Vector3D(user.Neck.X, user.Neck.Y, user.Neck.Z);
                    neck3D.Normalize();

                    float leftShoulderX = user.LeftShoulder.X;
                    float leftShoulderY = user.LeftShoulder.Y;
                    float leftShoulderZ = user.LeftShoulder.Z;
                    Vector3D leftShoulder3D = new Vector3D(user.LeftShoulder.X, user.LeftShoulder.Y, user.LeftShoulder.Z);
                    leftShoulder3D.Normalize();

                    float leftElbowX = user.LeftElbow.X;
                    float leftElbowY = user.LeftElbow.Y;
                    Vector3D leftElbow3D = new Vector3D(user.LeftElbow.X, user.LeftElbow.Y, user.LeftElbow.Z);
                    leftElbow3D.Normalize();

                    float leftHandX = user.LeftHand.X;
                    float leftHandY = user.LeftHand.Y;
                    float leftHandZ = user.LeftHand.Z;
                    Vector3D leftHand3D = new Vector3D(user.LeftHand.X, user.LeftHand.Y, user.LeftHand.Z);
                    leftHand3D.Normalize();

                    float rightShoulderX = user.RightShoulder.X;
                    float rightShoulderY = user.RightShoulder.Y;
                    float rightShoulderZ = user.RightShoulder.Z;
                    Vector3D rightShoulder3D = new Vector3D(user.RightShoulder.X, user.RightShoulder.Y, user.RightShoulder.Z);
                    rightShoulder3D.Normalize();

                    float frightHandX = user.RightShoulder.X;
                    float frightHandY = user.RightShoulder.Y;
                    float frightHandZ = user.RightShoulder.Z + 5;
                    Vector3D frightHand3D = new Vector3D(user.RightShoulder.X, user.RightShoulder.Y, user.RightShoulder.Z + 5);
                    frightHand3D.Normalize();

                    float rightElbowX = user.RightElbow.X;
                    float rightElbowY = user.RightElbow.Y;
                    Vector3D rightElbow3D = new Vector3D(user.RightElbow.X, user.RightElbow.Y, user.RightElbow.Z);
                    rightElbow3D.Normalize();

                    float rightHandX = user.RightHand.X;
                    float rightHandY = user.RightHand.Y;
                    float rightHandZ = user.RightHand.Z;
                    Vector3D rightHand3D = new Vector3D(user.RightHand.X, user.RightHand.Y, user.RightHand.Z);
                    rightHand3D.Normalize();

                    float waistX = user.Torso.X;
                    float waistY = user.Torso.Y;
                    float waistZ = user.Torso.Z;
                    Vector3D waist3D = new Vector3D(user.Torso.X, user.Torso.Y, user.Torso.Z);
                    waist3D.Normalize();

                    float leftHipX = user.LeftHip.X;
                    float leftHipY = user.LeftHip.Y;
                    float leftHipZ = user.LeftHip.Z;
                    Vector3D leftHip3D = new Vector3D(user.LeftHip.X, user.LeftHip.Y, user.LeftHip.Z);
                    leftHip3D.Normalize();

                    float leftKneeX = user.LeftKnee.X;
                    float leftKneeY = user.LeftKnee.Y;
                    Vector3D leftKnee3D = new Vector3D(user.LeftKnee.X, user.LeftKnee.Y, user.LeftKnee.Z);
                    leftKnee3D.Normalize();

                    float leftFootX = user.LeftFoot.X;
                    float leftFootY = user.LeftFoot.Y;
                    Vector3D leftFoot3D = new Vector3D(user.LeftFoot.X, user.LeftFoot.Y, user.LeftFoot.Z);
                    leftFoot3D.Normalize();

                    float rightHipX = user.RightHip.X;
                    float rightHipY = user.RightHip.Y;
                    float rightHipZ = user.RightHip.Z;
                    Vector3D rightHip3D = new Vector3D(user.RightHip.X, user.RightHip.Y, user.RightHip.Z);
                    rightHip3D.Normalize();

                    float rightKneeX = user.RightKnee.X;
                    float rightKneeY = user.RightKnee.Y;
                    Vector3D rightKnee3D = new Vector3D(user.RightKnee.X, user.RightKnee.Y, user.RightKnee.Z);
                    rightKnee3D.Normalize();


                    float rightFootX = user.RightFoot.X;
                    float rightFootY = user.RightFoot.Y;
                    Vector3D rightFoot3D = new Vector3D(user.RightFoot.X, user.RightFoot.Y, user.RightFoot.Z);
                    rightFoot3D.Normalize();
                    #endregion

                    dt.Rows.Clear();
                    allowedROMtoStart = true;
                    if (allowedROMtoStart == true)
                    {
                        #region calculate angle

                        #region Left Shoulders 2

                        Vector3D leftShoulderV1 = leftElbow3D - leftShoulder3D;
                        Vector3D leftShoulderV2 = leftHip3D - leftShoulder3D;
                        double leftShoulderAngle = Vector3D.AngleBetween(leftShoulderV1, leftShoulderV2);
                        now = Math.Round(leftShoulderAngle, 3);
                        if (!Double.IsNaN(now))
                        {
                            switch (maxJoint2 == 0 && minJoint2 == 0)
                            {
                                case true:
                                    maxJoint2 = now;
                                    minJoint2 = now;
                                    break;
                            }

                            switch (now > maxJoint2)
                            {
                                case true:
                                    maxJoint2 = now;
                                    break;
                            }
                            switch (now < minJoint2)
                            {
                                case true:
                                    minJoint2 = now;
                                    break;
                            }

                            DataRow rw = dt.NewRow();
                            dt.Rows.Add(rw);
                            rw["Joint"] = "Left Shoulder";
                            rw["Max Angle"] = maxJoint2.ToString();
                            rw["Min Angle"] = minJoint2.ToString();
                        }


                        #endregion
                        #region Right Shoulders 3

                        Vector3D rightShoulderV1 = rightElbow3D - rightShoulder3D;
                        Vector3D rightShoulderV2 = rightHip3D - rightShoulder3D;
                        double rightShoulderAngle = Vector3D.AngleBetween(rightShoulderV1, rightShoulderV2);
                        now = Math.Round(rightShoulderAngle, 3);
                        if (!Double.IsNaN(now))
                        {
                            switch (maxJoint3 == 0 && minJoint3 == 0)
                            {
                                case true:
                                    maxJoint3 = now;
                                    minJoint3 = now;
                                    break;
                            }

                            switch (now > maxJoint3)
                            {
                                case true:
                                    maxJoint3 = now;
                                    break;
                            }
                            switch (now < minJoint3)
                            {
                                case true:
                                    minJoint3 = now;
                                    break;
                            }

                            DataRow rw1 = dt.NewRow();
                            dt.Rows.Add(rw1);
                            rw1["Joint"] = "Right Shoulder";
                            rw1["Max Angle"] = maxJoint3.ToString();
                            rw1["Min Angle"] = minJoint3.ToString(); ;
                        }
                        #endregion
                        #region leftElbow

                        Vector3D leftElbowV1 = leftShoulder3D - leftElbow3D;
                        Vector3D leftElbowV2 = leftHand3D - leftElbow3D;
                        double leftElbowAngle = Vector3D.AngleBetween(leftElbowV1, leftElbowV2);
                        now = Math.Round(leftElbowAngle, 3);
                        if (!Double.IsNaN(now))
                        {
                            switch (maxJoint4 == 0 && minJoint4 == 0)
                            {
                                case true:
                                    maxJoint4 = now;
                                    minJoint4 = now;
                                    break;
                            }

                            switch (now > maxJoint4)
                            {
                                case true:
                                    maxJoint4 = now;
                                    break;
                            }
                            switch (now < minJoint4)
                            {
                                case true:
                                    minJoint4 = now;
                                    break;
                            }

                            DataRow rw2 = dt.NewRow();
                            dt.Rows.Add(rw2);
                            rw2["Joint"] = "Left Elbow";
                            rw2["Max Angle"] = maxJoint4.ToString();
                            rw2["Min Angle"] = minJoint4.ToString();
                        }
                        #endregion
                        #region rightElbow

                        Vector3D rightElbowV1 = rightShoulder3D - rightElbow3D;
                        Vector3D rightElbowV2 = rightHand3D - rightElbow3D;
                        double rightElbowAngle = Vector3D.AngleBetween(rightElbowV1, rightElbowV2);
                        now = Math.Round(rightElbowAngle, 3);
                        if (!Double.IsNaN(now))
                        {
                            switch (maxJoint5 == 0 && minJoint5 == 0)
                            {
                                case true:
                                    maxJoint5 = now;
                                    minJoint5 = now;
                                    break;
                            }

                            switch (now > maxJoint5)
                            {
                                case true:
                                    maxJoint5 = now;
                                    break;
                            }
                            switch (now < minJoint5)
                            {
                                case true:
                                    minJoint5 = now;
                                    break;
                            }

                            DataRow rw3 = dt.NewRow();
                            dt.Rows.Add(rw3);
                            rw3["Joint"] = "Right Elbow";
                            rw3["Max Angle"] = maxJoint5.ToString();
                            rw3["Min Angle"] = minJoint5.ToString();
                        }
                        #endregion
                        #region Torso

                        Vector3D spine = waist3D - neck3D;
                        Vector3D leftShoulder = leftShoulder3D - neck3D;
                        double Torso = Vector3D.AngleBetween(spine, leftShoulder);
                        now = Math.Round(Torso, 3);
                        if (!Double.IsNaN(now))
                        {
                            switch (maxJoint8 == 0 && minJoint8 == 0)
                            {
                                case true:
                                    maxJoint8 = now;
                                    minJoint8 = now;
                                    break;
                            }

                            switch (now > maxJoint8)
                            {
                                case true:
                                    maxJoint8 = now;
                                    break;
                            }
                            switch (now < minJoint8)
                            {
                                case true:
                                    minJoint8 = now;
                                    break;
                            }

                            DataRow rw4 = dt.NewRow();
                            dt.Rows.Add(rw4);
                            rw4["Joint"] = "Waist";
                            rw4["Max Angle"] = maxJoint8.ToString();
                            rw4["Min Angle"] = minJoint8.ToString();
                        }
                        #endregion
                        #region Left hips 9

                        Vector3D leftHipV1 = rightKnee3D - leftHip3D;
                        Vector3D leftHipV2 = leftKnee3D - leftHip3D;
                        double leftHipAngle = Vector3D.AngleBetween(leftHipV1, leftHipV2);
                        now = Math.Round(leftHipAngle, 3);
                        if (!Double.IsNaN(now))
                        {
                            switch (maxJoint9 == 0 && minJoint9 == 0)
                            {
                                case true:
                                    maxJoint9 = now;
                                    minJoint9 = now;
                                    break;
                            }

                            switch (now > maxJoint9)
                            {
                                case true:
                                    maxJoint9 = now;
                                    break;
                            }
                            switch (now < minJoint9)
                            {
                                case true:
                                    minJoint9 = now;
                                    break;
                            }


                            DataRow rw5 = dt.NewRow();
                            dt.Rows.Add(rw5);
                            rw5["Joint"] = "Left Hip";
                            rw5["Max Angle"] = maxJoint9.ToString();
                            rw5["Min Angle"] = minJoint9.ToString();
                        }
                        #endregion
                        #region Right hips 10

                        Vector3D rightHipV1 = leftKnee3D - rightHip3D;
                        Vector3D rightHipV2 = rightKnee3D - rightHip3D;
                        double rightHipAngle = Vector3D.AngleBetween(rightHipV1, rightHipV2);
                        now = Math.Round(rightHipAngle, 3);
                        if (!Double.IsNaN(now))
                        {
                            switch (maxJoint10 == 0 && minJoint10 == 0)
                            {
                                case true:
                                    maxJoint10 = now;
                                    minJoint10 = now;
                                    break;
                            }

                            switch (now > maxJoint10)
                            {
                                case true:
                                    maxJoint10 = now;
                                    break;
                            }
                            switch (now < minJoint10)
                            {
                                case true:
                                    minJoint10 = now;
                                    break;
                            }

                            DataRow rw6 = dt.NewRow();
                            dt.Rows.Add(rw6);
                            rw6["Joint"] = "Right Hip";
                            rw6["Max Angle"] = maxJoint10.ToString();
                            rw6["Min Angle"] = minJoint10.ToString();
                        }
                        #endregion
                        #region leftknee

                        Vector3D leftKneeV1 = leftHip3D - leftKnee3D;
                        Vector3D leftKneeV2 = leftFoot3D - leftKnee3D;
                        double leftKneeAngle = Vector3D.AngleBetween(leftKneeV1, leftKneeV2);
                        now = Math.Round(leftKneeAngle, 3);
                        if (!Double.IsNaN(now))
                        {
                            switch (maxJoint11 == 0 && minJoint11 == 0)
                            {
                                case true:
                                    maxJoint11 = now;
                                    minJoint11 = now;
                                    break;
                            }

                            switch (now > maxJoint11)
                            {
                                case true:
                                    maxJoint11 = now;
                                    break;
                            }
                            switch (now < minJoint11)
                            {
                                case true:
                                    minJoint11 = now;
                                    break;
                            }

                            DataRow rw7 = dt.NewRow();
                            dt.Rows.Add(rw7);
                            rw7["Joint"] = "Left Knee";
                            rw7["Max Angle"] = maxJoint11.ToString();
                            rw7["Min Angle"] = minJoint11.ToString();
                        }
                        #endregion
                        #region rightknee

                        Vector3D rightKneeV1 = rightHip3D - rightKnee3D;
                        Vector3D rightKneeV2 = rightFoot3D - rightKnee3D;
                        double rightKneeAngle = Vector3D.AngleBetween(rightKneeV1, rightKneeV2);
                        now = Math.Round(rightKneeAngle, 3);
                        if (!Double.IsNaN(now))
                        {
                            switch (maxJoint12 == 0 && minJoint12 == 0)
                            {
                                case true:
                                    maxJoint12 = now;
                                    minJoint12 = now;
                                    break;
                            }

                            switch (now > maxJoint12)
                            {
                                case true:
                                    maxJoint12 = now;
                                    break;
                            }
                            switch (now < minJoint12)
                            {
                                case true:
                                    minJoint12 = now;
                                    break;
                            }

                            DataRow rw8 = dt.NewRow();
                            dt.Rows.Add(rw8);
                            rw8["Joint"] = "Right Knee";
                            rw8["Max Angle"] = maxJoint12.ToString();
                            rw8["Min Angle"] = minJoint12.ToString();
                        }
                        #endregion

                        Vector3D frightShoulderV1 = frightHand3D - rightShoulder3D;
                        Vector3D frightShoulderV2 = rightHand3D - rightShoulder3D;
                        double frightShoulderAngle = Vector3D.AngleBetween(frightShoulderV1, frightShoulderV2);
                        now = Math.Round(frightShoulderAngle, 3);

                        #region display result

                        dgMeasurements.ItemsSource = ds.Tables[0].DefaultView;

                        #endregion

                        #endregion
                    }

                    #region Draw skeleton points
                    if (headX != 0 && headY != 0)
                    {
                        #region DrawLine for joints
                        Line myNeck = new Line();
                        myNeck.Stroke = Brushes.Black;
                        myNeck.X1 = Convert.ToDouble(headX + 15);
                        myNeck.Y1 = Convert.ToDouble(headY + 15);
                        myNeck.X2 = Convert.ToDouble(neckX + 15);
                        myNeck.Y2 = Convert.ToDouble(neckY + 15);
                        myNeck.StrokeThickness = 5;
                        canvasBody.Children.Add(myNeck);

                        Line myRightUpperLimbLower = new Line();
                        myRightUpperLimbLower.Stroke = Brushes.Black;
                        myRightUpperLimbLower.X1 = Convert.ToDouble(rightElbowX + 15);
                        myRightUpperLimbLower.Y1 = Convert.ToDouble(rightElbowY + 15);
                        myRightUpperLimbLower.X2 = Convert.ToDouble(rightHandX + 15);
                        myRightUpperLimbLower.Y2 = Convert.ToDouble(rightHandY + 15);
                        myRightUpperLimbLower.StrokeThickness = 5;
                        canvasBody.Children.Add(myRightUpperLimbLower);

                        Line myRightUpperLimbUpper = new Line();
                        myRightUpperLimbUpper.Stroke = Brushes.Black;
                        myRightUpperLimbUpper.X1 = Convert.ToDouble(rightElbowX + 15);
                        myRightUpperLimbUpper.Y1 = Convert.ToDouble(rightElbowY + 15);
                        myRightUpperLimbUpper.X2 = Convert.ToDouble(rightShoulderX + 15);
                        myRightUpperLimbUpper.Y2 = Convert.ToDouble(rightShoulderY + 15);
                        myRightUpperLimbUpper.StrokeThickness = 5;
                        canvasBody.Children.Add(myRightUpperLimbUpper);

                        Line myRightShoulder = new Line();
                        myRightShoulder.Stroke = Brushes.Black;
                        myRightShoulder.X1 = Convert.ToDouble(neckX + 15);
                        myRightShoulder.Y1 = Convert.ToDouble(neckY + 15);
                        myRightShoulder.X2 = Convert.ToDouble(rightShoulderX + 15);
                        myRightShoulder.Y2 = Convert.ToDouble(rightShoulderY + 15);
                        myRightShoulder.StrokeThickness = 5;
                        canvasBody.Children.Add(myRightShoulder);

                        Line myLeftUpperLimbLower = new Line();
                        myLeftUpperLimbLower.Stroke = Brushes.Black;
                        myLeftUpperLimbLower.X1 = Convert.ToDouble(leftElbowX + 15);
                        myLeftUpperLimbLower.Y1 = Convert.ToDouble(leftElbowY + 15);
                        myLeftUpperLimbLower.X2 = Convert.ToDouble(leftHandX + 15);
                        myLeftUpperLimbLower.Y2 = Convert.ToDouble(leftHandY + 15);
                        myLeftUpperLimbLower.StrokeThickness = 5;
                        canvasBody.Children.Add(myLeftUpperLimbLower);

                        Line myLeftUpperLimbUpper = new Line();
                        myLeftUpperLimbUpper.Stroke = Brushes.Black;
                        myLeftUpperLimbUpper.X1 = Convert.ToDouble(leftElbowX + 15);
                        myLeftUpperLimbUpper.Y1 = Convert.ToDouble(leftElbowY + 15);
                        myLeftUpperLimbUpper.X2 = Convert.ToDouble(leftShoulderX + 15);
                        myLeftUpperLimbUpper.Y2 = Convert.ToDouble(leftShoulderY + 15);
                        myLeftUpperLimbUpper.StrokeThickness = 5;
                        canvasBody.Children.Add(myLeftUpperLimbUpper);

                        Line myLeftShoulder = new Line();
                        myLeftShoulder.Stroke = Brushes.Black;
                        myLeftShoulder.X1 = Convert.ToDouble(neckX + 15);
                        myLeftShoulder.Y1 = Convert.ToDouble(neckY + 15);
                        myLeftShoulder.X2 = Convert.ToDouble(leftShoulderX + 15);
                        myLeftShoulder.Y2 = Convert.ToDouble(leftShoulderY + 15);
                        myLeftShoulder.StrokeThickness = 5;
                        canvasBody.Children.Add(myLeftShoulder);

                        //Legs
                        Line myLeftLowerLimbLower = new Line();
                        myLeftLowerLimbLower.Stroke = Brushes.Black;
                        myLeftLowerLimbLower.X1 = Convert.ToDouble(leftFootX + 15);
                        myLeftLowerLimbLower.Y1 = Convert.ToDouble(leftFootY + 15);
                        myLeftLowerLimbLower.X2 = Convert.ToDouble(leftKneeX + 15);
                        myLeftLowerLimbLower.Y2 = Convert.ToDouble(leftKneeY + 15);
                        myLeftLowerLimbLower.StrokeThickness = 5;
                        canvasBody.Children.Add(myLeftLowerLimbLower);

                        Line myLeftLowerLimbUpper = new Line();
                        myLeftLowerLimbUpper.Stroke = Brushes.Black;
                        myLeftLowerLimbUpper.X1 = Convert.ToDouble(leftKneeX + 15);
                        myLeftLowerLimbUpper.Y1 = Convert.ToDouble(leftKneeY + 15);
                        myLeftLowerLimbUpper.X2 = Convert.ToDouble(leftHipX + 15);
                        myLeftLowerLimbUpper.Y2 = Convert.ToDouble(leftHipY + 15);
                        myLeftLowerLimbUpper.StrokeThickness = 5;
                        canvasBody.Children.Add(myLeftLowerLimbUpper);

                        Line myRightLowerLimbLower = new Line();
                        myRightLowerLimbLower.Stroke = Brushes.Black;
                        myRightLowerLimbLower.X1 = Convert.ToDouble(rightFootX + 15);
                        myRightLowerLimbLower.Y1 = Convert.ToDouble(rightFootY + 15);
                        myRightLowerLimbLower.X2 = Convert.ToDouble(rightKneeX + 15);
                        myRightLowerLimbLower.Y2 = Convert.ToDouble(rightKneeY + 15);
                        myRightLowerLimbLower.StrokeThickness = 5;
                        canvasBody.Children.Add(myRightLowerLimbLower);

                        Line myRightLowerLimbUpper = new Line();
                        myRightLowerLimbUpper.Stroke = Brushes.Black;
                        myRightLowerLimbUpper.X1 = Convert.ToDouble(rightKneeX + 15);
                        myRightLowerLimbUpper.Y1 = Convert.ToDouble(rightKneeY + 15);
                        myRightLowerLimbUpper.X2 = Convert.ToDouble(rightHipX + 15);
                        myRightLowerLimbUpper.Y2 = Convert.ToDouble(rightHipY + 15);
                        myRightLowerLimbUpper.StrokeThickness = 5;
                        canvasBody.Children.Add(myRightLowerLimbUpper);

                        Line myLeftLowerWrist = new Line();
                        myLeftLowerWrist.Stroke = Brushes.Black;
                        myLeftLowerWrist.X1 = Convert.ToDouble(waistX + 15);
                        myLeftLowerWrist.Y1 = Convert.ToDouble(waistY + 15);
                        myLeftLowerWrist.X2 = Convert.ToDouble(leftHipX + 15);
                        myLeftLowerWrist.Y2 = Convert.ToDouble(leftHipY + 15);
                        myLeftLowerWrist.StrokeThickness = 5;
                        canvasBody.Children.Add(myLeftLowerWrist);

                        Line myRightLowerWrist = new Line();
                        myRightLowerWrist.Stroke = Brushes.Black;
                        myRightLowerWrist.X1 = Convert.ToDouble(waistX + 15);
                        myRightLowerWrist.Y1 = Convert.ToDouble(waistY + 15);
                        myRightLowerWrist.X2 = Convert.ToDouble(rightHipX + 15);
                        myRightLowerWrist.Y2 = Convert.ToDouble(rightHipY + 15);
                        myRightLowerWrist.StrokeThickness = 5;
                        canvasBody.Children.Add(myRightLowerWrist);

                        Line myLeftUpperWrist = new Line();
                        myLeftUpperWrist.Stroke = Brushes.Black;
                        myLeftUpperWrist.X1 = Convert.ToDouble(waistX + 15);
                        myLeftUpperWrist.Y1 = Convert.ToDouble(waistY + 15);
                        myLeftUpperWrist.X2 = Convert.ToDouble(leftShoulderX + 15);
                        myLeftUpperWrist.Y2 = Convert.ToDouble(leftShoulderY + 15);
                        myLeftUpperWrist.StrokeThickness = 5;
                        canvasBody.Children.Add(myLeftUpperWrist);

                        Line myRightUpperWrist = new Line();
                        myRightUpperWrist.Stroke = Brushes.Black;
                        myRightUpperWrist.X1 = Convert.ToDouble(waistX + 15);
                        myRightUpperWrist.Y1 = Convert.ToDouble(waistY + 15);
                        myRightUpperWrist.X2 = Convert.ToDouble(rightShoulderX + 15);
                        myRightUpperWrist.Y2 = Convert.ToDouble(rightShoulderY + 15);
                        myRightUpperWrist.StrokeThickness = 5;
                        canvasBody.Children.Add(myRightUpperWrist);
                        #endregion

                        #region DrawCircle for each point
                        DrawCircle(headX, headY, userColor);
                        //DrawCircle(neckX, neckY, userColor);
                        //DrawCircle(leftShoulderX, leftShoulderY, userColor);
                        //DrawCircle(leftElbowX, leftElbowY, userColor);
                        //DrawCircle(leftHandX, leftHandY, userColor);
                        //DrawCircle(waistX, waistY, userColor);
                        //DrawCircle(rightShoulderX, rightShoulderY, userColor);
                        //DrawCircle(rightElbowX, rightElbowY, userColor);
                        //DrawCircle(rightHandX, rightHandY, userColor);
                        //DrawCircle(leftHipX, leftHipY, userColor);
                        //DrawCircle(leftKneeX, leftKneeY, userColor);
                        //DrawCircle(leftFootX, leftFootY, userColor);
                        //DrawCircle(rightHipX, rightHipY, userColor);
                        //DrawCircle(rightKneeX, rightKneeY, userColor);
                        //DrawCircle(rightFootX, rightFootY, userColor);
                        gotUser = true;
                        #endregion
                    }
                    else
                    {
                        stopKinect();
                        startKinect();
                    }
                    #endregion

                    //#region Draw skeleton points
                    //if (headX != 0 && headY != 0)
                    //{
                    //    #region DrawCircle for each point
                    //    DrawCircle(headX, headY, userColor);
                    //    DrawCircle(neckX, neckY, userColor);
                    //    DrawCircle(leftShoulderX, leftShoulderY, userColor);
                    //    DrawCircle(leftElbowX, leftElbowY, userColor);
                    //    DrawCircle(leftHandX, leftHandY, userColor);
                    //    DrawCircle(waistX, waistY, userColor);
                    //    DrawCircle(rightShoulderX, rightShoulderY, userColor);
                    //    DrawCircle(rightElbowX, rightElbowY, userColor);
                    //    DrawCircle(rightHandX, rightHandY, userColor);
                    //    DrawCircle(leftHipX, leftHipY, userColor);
                    //    DrawCircle(leftKneeX, leftKneeY, userColor);
                    //    DrawCircle(leftFootX, leftFootY, userColor);
                    //    DrawCircle(rightHipX, rightHipY, userColor);
                    //    DrawCircle(rightKneeX, rightKneeY, userColor);
                    //    DrawCircle(rightFootX, rightFootY, userColor);
                    //    gotUser = true;
                    //    #endregion
                    //}
                    //else
                    //{
                    //    stopKinect();
                    //    startKinect();
                    //}
                    //#endregion
                }
            });
            #endregion
        }

        //void DrawCircle(float positionX, float positionY, Color color)
        //{
        //    Ellipse ellipse = new Ellipse
        //    {
        //        Fill = new SolidColorBrush(color),
        //        Width = 30,
        //        Height = 30,
        //        Margin = new Thickness(positionX, positionY + 15, 0, 0)
        //    };

        //    LayoutRoot.Children.Add(ellipse);
        //}

        private void stopKinect()
        {
  
            try
            {
                try
                {
                    BWstarted = false;
                    _skeleton.Stop();
                    _worker.CancelAsync();
                    _worker.Dispose();
                    canvasBody.Children.Clear();
                }
                catch (NullReferenceException) { throw new Exception(); }
            }
            catch (Exception) { }
            gotUser = false;
        }

        private void startKinect()
        {
            try
            {
                BWstarted = true;
                _worker.RunWorkerAsync();

                //CompositionTarget.Rendering += CompositionTarget_Rendering;
                //_skeleton.UsersUpdated += _skeleton_UsersUpdated;
                //_worker.RunWorkerAsync();
                canvasBody.Children.Clear();
            }
            catch (Exception) { }
            gotUser = false;
        }


        # endregion

        # region speech

        private SpeechRecognitionEngine _recognizer;

        void _recognizer_SpeechRecognized(object sender, SpeechRecognizedEventArgs e)
        {
            if (disableVoice == true)
            {
                foreach (RecognizedWordUnit word in e.Result.Words)
                {
                    switch (word.Text)
                    {
                        case "start":
                            initalizeStartKinectSDK();
                            break;
                        case "stop":
                            if (uploadToAzure == false)
                            {
                                try
                                {
                                    nui.Uninitialize();
                                }
                                catch (Exception)
                                {
                                }

                                svc.createNewSessionCompleted += new EventHandler<tara_wcf.createNewSessionCompletedEventArgs>(svc_createNewSessionCompleted);
                                svc.createNewSessionAsync(MainPage.patientID, 10);

                                uploadToAzure = true;
                            }
                            break;
                    }
                }
            }

            //throw new NotImplementedException();
        }

        void recongizer_SpeechRecognized(object sender, SpeechRecognizedEventArgs e)
        {
            //label1.Content = e.Result.Text;
            //MessageBox.Show("you said:" + e.Result.Text);
            //throw new NotImplementedException();
        }

        #endregion
        bool disableVoice = true;
        private void Page_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.F1)
            {
                if (disableVoice == true)
                    disableVoice = false;
                else
                    disableVoice = true;
            }
        }
    }
}